{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "b518b04cbfe0"
      },
      "source": [
        "##### Copyright 2020 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "906e07f6e562"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "c359f002e834"
      },
      "source": [
        "# TensorFlow Cloud로 Keras 모델 훈련하기"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "f5c893a15fac"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td><a target=\"_blank\" href=\"https://www.tensorflow.org/guide/keras/training_keras_models_on_cloud\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\">TensorFlow.org에서 보기</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/ko/guide/keras/training_keras_models_on_cloud.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\">Google Colab에서 실행</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/keras/training_keras_models_on_cloud.ipynb\">     <img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\">    GitHub에서 소스 보기</a></td>\n",
        "  <td><a href=\"https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/ko/guide/keras/training_keras_models_on_cloud.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\">노트북 다운로드</a></td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "b1c0246f8536"
      },
      "source": [
        "## 소개\n",
        "\n",
        "[TensorFlow Cloud](https://github.com/tensorflow/cloud)는 로컬 디버깅에서 GCP의 분산 훈련으로 원활하게 전환할 수 있도록 API를 제공하는 Python 패키지입니다. 클라우드에서 TensorFlow 모델의 훈련 프로세스를 단일의 간단한 함수 호출로 단순화하여 최소한의 설정만 필요하고 모델을 변경하지 않아도 됩니다. TensorFlow Cloud는 VM 인스턴스 생성 및 모델 배포 전략과 같은 클라우드 관련 작업을 자동으로 처리합니다. 이 가이드는 TensorFlow Cloud를 통해 Google Cloud와 상호 작용하는 방법과 TensorFlow Cloud에서 제공되는 다양한 기능을 보여줍니다. 가장 간단한 사용 사례부터 시작하겠습니다."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "e015c75faba2"
      },
      "source": [
        "## Setup\n",
        "\n",
        "TensorFlow Cloud를 설치하고 이 가이드에서 필요한 패키지를 가져오는 것부터 시작하겠습니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "99e5bc5e0ab8"
      },
      "outputs": [],
      "source": [
        "!pip install -q tensorflow_cloud"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "26113effabca"
      },
      "outputs": [],
      "source": [
        "import tensorflow as tf\n",
        "import tensorflow_cloud as tfc\n",
        "\n",
        "from tensorflow import keras\n",
        "from tensorflow.keras import layers"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "e8568395c87b"
      },
      "source": [
        "## API 개요: 첫 번째 엔드 투 엔드 예제\n",
        "\n",
        "다음 CNN과 같은 Keras 모델 훈련 스크립트로 시작하겠습니다.\n",
        "\n",
        "```python\n",
        "(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()\n",
        "\n",
        "model = keras.Sequential(\n",
        "    [\n",
        "        keras.Input(shape=(28, 28)),\n",
        "        # Use a Rescaling layer to make sure input values are in the [0, 1] range.\n",
        "        layers.experimental.preprocessing.Rescaling(1.0 / 255),\n",
        "        # The original images have shape (28, 28), so we reshape them to (28, 28, 1)\n",
        "        layers.Reshape(target_shape=(28, 28, 1)),\n",
        "        # Follow-up with a classic small convnet\n",
        "        layers.Conv2D(32, 3, activation=\"relu\"),\n",
        "        layers.MaxPooling2D(2),\n",
        "        layers.Conv2D(32, 3, activation=\"relu\"),\n",
        "        layers.MaxPooling2D(2),\n",
        "        layers.Conv2D(32, 3, activation=\"relu\"),\n",
        "        layers.Flatten(),\n",
        "        layers.Dense(128, activation=\"relu\"),\n",
        "        layers.Dense(10),\n",
        "    ]\n",
        ")\n",
        "\n",
        "model.compile(\n",
        "    optimizer=keras.optimizers.Adam(),\n",
        "    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),\n",
        "    metrics=keras.metrics.SparseCategoricalAccuracy(),\n",
        ")\n",
        "\n",
        "model.fit(x_train, y_train, epochs=20, batch_size=128, validation_split=0.1)\n",
        "```"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "514f51a9a45d"
      },
      "source": [
        "Google Cloud에서 이 모델을 훈련하려면 가져오기 전에 스크립트의 시작 부분에 `run()` 호출을 추가하기만 하면 됩니다.\n",
        "\n",
        "```python\n",
        "tfc.run()\n",
        "```"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "6e38288bb617"
      },
      "source": [
        "TensorFlow Cloud를 사용할 때 VM 인스턴스의 생성 및 배포 전략과 같은 클라우드 관련 작업에 대해 걱정할 필요가 없습니다. API에는 모든 매개변수에 대한 지능적인 기본값이 포함되어 있습니다. 모든 것이 구성 가능하지만, 많은 모델이 기본값을 사용할 수 있습니다.\n",
        "\n",
        "`run()`을 호출하면 TensorFlow Cloud는 다음을 수행합니다.\n",
        "\n",
        "- Python 스크립트 또는 노트북 배포를 준비합니다.\n",
        "- 필요한 종속성이 있는 Docker 이미지로 변환합니다.\n",
        "- GCP GPU 기반 VM에서 훈련 작업을 실행합니다.\n",
        "- 관련 로그 및 작업 정보를 스트리밍합니다.\n",
        "\n",
        "기본 VM 구성은 CPU 코어 8개와 Tesla T4 GPU 1개가 있는 최고 1명과 작업자 0명입니다."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "3ab860e037c9"
      },
      "source": [
        "## Google Cloud 구성\n",
        "\n",
        "Cloud 훈련을 위한 적절한 경로를 촉진하려면 몇 가지 첫 번째 설정을 수행해야 합니다. Google Cloud를 처음 사용하는 경우, 수행해야 할 몇 가지 예비 단계가 있습니다.\n",
        "\n",
        "1. GCP 프로젝트를 만듭니다.\n",
        "2. AI Platform 서비스를 활성화합니다.\n",
        "3. 서비스 계정을 만듭니다.\n",
        "4. 인증 키를 다운로드합니다.\n",
        "5. Cloud Storage 버킷을 만듭니다.\n",
        "\n",
        "자세한 최초 설정 지침은 [TensorFlow Cloud README](https://github.com/tensorflow/cloud#setup-instructions)에서 찾을 수 있으며, 추가 설정 예제는 [TensorFlow 블로그](https://blog.tensorflow.org/2020/08/train-your-tensorflow-model-on-google.html) 에 표시됩니다.\n",
        "\n",
        "## 일반적인 워크플로 및 클라우드 스토리지\n",
        "\n",
        "대부분의 경우, Google Cloud에서 모델을 훈련한 후 모델을 검색하려고 합니다. 이를 위해서는 원격으로 훈련하는 동안 저장 및 로드를 Cloud Storage로 리디렉션하는 것이 중요합니다. 다양한 작업을 위해 TensorFlow Cloud를 Cloud Storage 버킷으로 리디렉션할 수 있습니다. 스토리지 버킷을 사용하여 대규모 훈련 데이터세트를 저장 및 로드하고, 콜백 로그 또는 모델 가중치를 저장하고, 훈련된 모델 파일을 저장할 수 있습니다. 시작하려면, 모델을 Cloud Storage에 저장하도록 `fit()`를 구성하고 훈련 진행 상황을 추적하도록 TensorBoard 모니터링을 설정하겠습니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "af5077731187"
      },
      "outputs": [],
      "source": [
        "def create_model():\n",
        "    model = keras.Sequential(\n",
        "        [\n",
        "            keras.Input(shape=(28, 28)),\n",
        "            layers.experimental.preprocessing.Rescaling(1.0 / 255),\n",
        "            layers.Reshape(target_shape=(28, 28, 1)),\n",
        "            layers.Conv2D(32, 3, activation=\"relu\"),\n",
        "            layers.MaxPooling2D(2),\n",
        "            layers.Conv2D(32, 3, activation=\"relu\"),\n",
        "            layers.MaxPooling2D(2),\n",
        "            layers.Conv2D(32, 3, activation=\"relu\"),\n",
        "            layers.Flatten(),\n",
        "            layers.Dense(128, activation=\"relu\"),\n",
        "            layers.Dense(10),\n",
        "        ]\n",
        "    )\n",
        "\n",
        "    model.compile(\n",
        "        optimizer=keras.optimizers.Adam(),\n",
        "        loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),\n",
        "        metrics=keras.metrics.SparseCategoricalAccuracy(),\n",
        "    )\n",
        "    return model\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5f2e65d8f3a6"
      },
      "source": [
        "훈련 중에 생성된 TensorBoard 로그 및 모델 체크포인트를 클라우드 스토리지 버킷에 저장해 보겠습니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "fdc4f951281c"
      },
      "outputs": [],
      "source": [
        "import datetime\n",
        "import os\n",
        "\n",
        "# Note: Please change the gcp_bucket to your bucket name.\n",
        "gcp_bucket = \"keras-examples\"\n",
        "\n",
        "checkpoint_path = os.path.join(\"gs://\", gcp_bucket, \"mnist_example\", \"save_at_{epoch}\")\n",
        "\n",
        "tensorboard_path = os.path.join(  # Timestamp included to enable timeseries graphs\n",
        "    \"gs://\", gcp_bucket, \"logs\", datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\")\n",
        ")\n",
        "\n",
        "callbacks = [\n",
        "    # TensorBoard will store logs for each epoch and graph performance for us.\n",
        "    keras.callbacks.TensorBoard(log_dir=tensorboard_path, histogram_freq=1),\n",
        "    # ModelCheckpoint will save models after each epoch for retrieval later.\n",
        "    keras.callbacks.ModelCheckpoint(checkpoint_path),\n",
        "    # EarlyStopping will terminate training when val_loss ceases to improve.\n",
        "    keras.callbacks.EarlyStopping(monitor=\"val_loss\", patience=3),\n",
        "]\n",
        "\n",
        "model = create_model()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "45d6210176e6"
      },
      "source": [
        "여기서는 Keras에서 직접 데이터를 로드합니다. 일반적으로 데이터세트를 Cloud Storage 버킷에 저장하는 것이 가장 좋지만, TensorFlow Cloud는 로컬에 저장된 데이터세트도 수용할 수 있습니다. 이 가이드의 다중 파일 섹션에서 다룹니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "bd4ef6ffa611"
      },
      "outputs": [],
      "source": [
        "(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "b1d2a2688887"
      },
      "source": [
        "[TensorFlow Cloud](https://github.com/tensorflow/cloud) API는 코드가 로컬에서 실행되는지 클라우드에서 실행되는지를 확인하기 위해 `remote()` 함수를 제공합니다. 이를 통해 로컬 및 원격 실행을 위한 `fit()` 매개변수를 별도로 지정할 수 있으며 로컬 머신에 과부하를 주지 않고 쉽게 디버깅할 수 있는 수단을 제공합니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "cfab9ff41fd5"
      },
      "outputs": [],
      "source": [
        "if tfc.remote():\n",
        "    epochs = 100\n",
        "    callbacks = callbacks\n",
        "    batch_size = 128\n",
        "else:\n",
        "    epochs = 5\n",
        "    batch_size = 64\n",
        "    callbacks = None\n",
        "\n",
        "model.fit(x_train, y_train, epochs=epochs, callbacks=callbacks, batch_size=batch_size)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9b27c0b3b7db"
      },
      "source": [
        "훈련이 완료된 후 모델을 GCS에 저장하겠습니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "b00451dcfeab"
      },
      "outputs": [],
      "source": [
        "save_path = os.path.join(\"gs://\", gcp_bucket, \"mnist_example\")\n",
        "\n",
        "if tfc.remote():\n",
        "    model.save(save_path)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0dceb5b7a173"
      },
      "source": [
        "로컬 Docker 인스턴스 대신 Docker 이미지 구축에 이 스토리지 버킷을 사용할 수도 있습니다. 이를 위해 `docker_image_bucket_name` 매개변수에 버킷을 추가하기만 하면 됩니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "13200523ed93"
      },
      "outputs": [],
      "source": [
        "# docs_infra: no_execute\n",
        "tfc.run(docker_image_bucket_name=gcp_bucket)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "060a2112c34e"
      },
      "source": [
        "모델을 훈련한 후 저장된 모델을 로드하고 TensorBoard 로그를 보고 성능을 모니터링할 수 있습니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "b8d773e2cfb7"
      },
      "outputs": [],
      "source": [
        "# docs_infra: no_execute\n",
        "model = keras.models.load_model(save_path)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "05d1d68bae5a"
      },
      "outputs": [],
      "source": [
        "!#docs_infra: no_execute\n",
        "!tensorboard dev upload --logdir \"gs://keras-examples-jonah/logs/fit\" --name \"Guide MNIST\""
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "3785ece03a8f"
      },
      "source": [
        "## 대규모 프로젝트\n",
        "\n",
        "대부분의 경우, Keras 모델을 포함하는 프로젝트는 둘 이상의 Python 스크립트를 포함하거나 외부 데이터 또는 특정 종속성을 포함할 수 있습니다. TensorFlow Cloud는 대규모 배포에 전적으로 유연하며 프로젝트를 지원하는 다양한 지능형 기능을 제공합니다.\n",
        "\n",
        "### 진입점: Python 스크립트 및 Jupyter 노트북 지원\n",
        "\n",
        "`run()` API에 대한 호출이 모델 훈련 코드와 같은 Python 스크립트에 항상 포함되는 것은 아닙니다. 이를 위해 `entry_point` 매개변수를 제공합니다. `entry_point` 매개변수는 모델 훈련 코드가 있는 Python 스크립트 또는 노트북을 지정하는 데 사용할 수 있습니다. 모델과 같은 스크립트에서 `run()`을 호출할 때 `entry_point` 기본값인 `None` 사용하세요.\n",
        "\n",
        "### `pip` 종속성\n",
        "\n",
        "프로젝트에서 추가 `pip` 종속성을 호출하는 경우, `requirements.txt` 파일을 포함하여 추가 필수 라이브러리를 지정할 수 있습니다. 이 파일에 필요한 모든 종속성의 목록을 입력하면 TensorFlow Cloud가 이를 클라우드 빌드에 통합하는 작업을 처리합니다.\n",
        "\n",
        "### Python 노트북\n",
        "\n",
        "TensorFlow Cloud는 Python 노트북에서도 실행할 수 있습니다. 또한, 필요한 경우 지정된 `entry_point`가 노트북이 될 수 있습니다. 노트북에서의 TensorFlow Cloud는 스크립트와 비교할 때 염두에 두어야 할 두 가지 주요 차이점이 있습니다.\n",
        "\n",
        "- 노트북 내에서 `run()`을 호출 할 때 Docker 이미지를 빌드하고 저장하기 위해 Cloud Storage 버킷을 지정해야 합니다.\n",
        "- GCloud 인증은 프로젝트 사양 없이 전적으로 인증 키를 통해 이루어집니다. 노트북에서 TensorFlow Cloud를 사용하는 워크플로의 예는 이 가이드의 \"종합적으로 살펴보기\" 섹션에서 제공됩니다.\n",
        "\n",
        "### 다중 파일 프로젝트\n",
        "\n",
        "모델이 추가 파일에 의존하는 경우, 해당 파일이 지정된 진입점의 같은 디렉토리(또는 하위 디렉토리)에 있는지 확인하기만 하면 됩니다. 지정된 `entry_point`와 같은 디렉토리에 저장된 모든 파일은 Docker 이미지에 포함되며 `entry_point`와 인접한 하위 디렉토리에 저장된 모든 파일도 포함됩니다. 이것은 `pip`를 통해 얻을 수없는 종속성에 대해서도 마찬가지입니다.\n",
        "\n",
        "추가 pip 종속성이 있는 사용자 정의 진입점 및 다중 파일 프로젝트의 예는 [TensorFlow Cloud Repository](https://github.com/tensorflow/cloud/tree/master/src/python/tensorflow_cloud/core/tests/examples/multi_file_example)에서 이 다중 파일 예제를 참조하세요. 간결함을 위해 예제의 `run()` 호출을 포함합니다.\n",
        "\n",
        "```python\n",
        "tfc.run(\n",
        "    docker_image_bucket_name=gcp_bucket,\n",
        "    entry_point=\"train_model.py\",\n",
        "    requirements=\"requirements.txt\"\n",
        ")\n",
        "```"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "997e3f89c734"
      },
      "source": [
        "## 머신 구성 및 분산 훈련\n",
        "\n",
        "모델 훈련에는 모델 또는 데이터세트의 크기에 따라 다양한 리소스가 필요할 수 있습니다. 여러 GPU가 있는 구성을 고려할 때, 맞춤 조정 [배포 전략](https://www.tensorflow.org/guide/distributed_training)을 선택하는 것이 중요해집니다. 다음은 몇 가지 가능한 구성에 대한 설명입니다.\n",
        "\n",
        "### 다중 작업자 배포\n",
        "\n",
        "`COMMON_MACHINE_CONFIGS`를 사용하여 1개의 최고 CPU와 4개의 작업자 GPU를 지정할 수 있습니다.\n",
        "\n",
        "```python\n",
        "tfc.run(\n",
        "    docker_image_bucket_name=gcp_bucket,\n",
        "    chief_config=tfc.COMMON_MACHINE_CONFIGS['CPU'],\n",
        "    worker_count=2,\n",
        "    worker_config=tfc.COMMON_MACHINE_CONFIGS['T4_4X']\n",
        ")\n",
        "```\n",
        "\n",
        "기본적으로 TensorFlow Cloud는 `chief_config` , `worker_config` 및 `worker_count` 매개 변수를 사용하는 간단한 공식으로 머신 구성에 가장 적합한 배포 전략을 선택합니다.\n",
        "\n",
        "- 지정된 GPU 수가 0보다 크면 `tf.distribute.MirroredStrategy` 가 선택됩니다.\n",
        "- 작업자 수가 0보다 크면 가속기 유형에 따라 `tf.distribute.experimental.MultiWorkerMirroredStrategy` 또는 `tf.distribute.experimental.TPUStrategy` 가 선택됩니다.\n",
        "- 그렇지 않으면 `tf.distribute.OneDeviceStrategy`가 선택됩니다."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "e0d938efab72"
      },
      "source": [
        "### TPU 분포\n",
        "\n",
        "다음과 같이 TPU에서 같은 모델을 훈련해 보겠습니다.\n",
        "\n",
        "```python\n",
        "tfc.run(\n",
        "    docker_image_bucket_name=gcp_bucket,\n",
        "    chief_config=tfc.COMMON_MACHINE_CONFIGS[\"CPU\"],\n",
        "    worker_count=1,\n",
        "    worker_config=tfc.COMMON_MACHINE_CONFIGS[\"TPU\"]\n",
        ")\n",
        "```"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "d1dec83a0b19"
      },
      "source": [
        "### 사용자 정의 배포 전략\n",
        "\n",
        "사용자 정의 배포 전략을 지정하려면, [배포 훈련 가이드](https://www.tensorflow.org/guide/distributed_training) 에 따라 정상적으로 코드 형식을 지정하고 `distribution_strategy`를 `None`으로 설정합니다. 아래에서는 같은 MNIST 모델에 대한 자체 배포 전략을 지정해 보겠습니다.\n",
        "\n",
        "```python\n",
        "(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()\n",
        "\n",
        "mirrored_strategy = tf.distribute.MirroredStrategy()\n",
        "with mirrored_strategy.scope():\n",
        "  model = create_model()\n",
        "\n",
        "if tfc.remote():\n",
        "    epochs = 100\n",
        "    batch_size = 128\n",
        "else:\n",
        "    epochs = 10\n",
        "    batch_size = 64\n",
        "    callbacks = None\n",
        "\n",
        "model.fit(\n",
        "    x_train, y_train, epochs=epochs, callbacks=callbacks, batch_size=batch_size\n",
        ")\n",
        "\n",
        "tfc.run(\n",
        "    docker_image_bucket_name=gcp_bucket,\n",
        "    chief_config=tfc.COMMON_MACHINE_CONFIGS['CPU'],\n",
        "    worker_count=2,\n",
        "    worker_config=tfc.COMMON_MACHINE_CONFIGS['T4_4X'],\n",
        "    distribution_strategy=None\n",
        ")\n",
        "```"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0a50b62bf672"
      },
      "source": [
        "## 사용자 정의 Docker 이미지\n",
        "\n",
        "기본적으로 TensorFlow Cloud는 Google에서 제공하고 현재 TensorFlow 버전에 해당하는 [Docker 기본 이미지를](https://hub.docker.com/r/tensorflow/tensorflow/) 사용합니다. 그러나 필요한 경우, 빌드 요구 사항에 맞게 사용자 정의 Docker 이미지를 지정할 수도 있습니다. 이 예에서는 이전 버전의 TensorFlow에서 Docker 이미지를 지정합니다.\n",
        "\n",
        "```python\n",
        "tfc.run(\n",
        "    docker_image_bucket_name=gcp_bucket,\n",
        "    base_docker_image=\"tensorflow/tensorflow:2.1.0-gpu\"\n",
        ")\n",
        "```"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "bb659015ffad"
      },
      "source": [
        "## 추가 메트릭\n",
        "\n",
        "특정 레이블로 Cloud 작업에 태그를 지정하거나 Cloud 훈련 중에 모델의 로그를 스트리밍하는 것이 유용할 수 있습니다. 기록 보관을 위해 모든 Cloud 작업에 적절한 레이블을 유지하는 것이 좋습니다. 이를 위해 `run()`은 Cloud 빌드 로그에서 볼 수 있는 최대 64개의 키-값 쌍의 레이블 사전을 허용합니다. epoch 성능 및 모델 저장 내부 사항과 같은 로그는 `tfc.run`을 실행하여 제공되는 링크를 사용하여 액세스하거나 `stream_logs` 플래그를 사용하여 로컬 터미널에 인쇄할 수 있습니다.\n",
        "\n",
        "```python\n",
        "job_labels = {\"job\": \"mnist-example\", \"team\": \"keras-io\", \"user\": \"jonah\"}\n",
        "\n",
        "tfc.run(\n",
        "    docker_image_bucket_name=gcp_bucket,\n",
        "    job_labels=job_labels,\n",
        "    stream_logs=True\n",
        ")\n",
        "```"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "b34a2e8e09c3"
      },
      "source": [
        "## 종합적으로 살펴보기\n",
        "\n",
        "이 가이드에 설명된 많은 기능을 사용하는 심층적인 Colab의 경우, [이 예제](https://github.com/tensorflow/cloud/blob/master/src/python/tensorflow_cloud/core/tests/examples/dogs_classification.ipynb)를 따라 특성 추출을 사용하여 사진에서 개 품종을 인식하도록 최첨단 모델을 훈련하세요."
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [],
      "name": "training_keras_models_on_cloud.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
